package Thread;

/**
 * 变量的内存可见性例子
 *
 * 方法一
 * 执行下面的程序，你会发现，不使volatile，控制台永远都不会输出 “主线程访问到 flag 变量” 这句话。
 * 我们可以看到，子线程执行时已经将 flag 设置成 true，但主线程执行时没有读到 flag 的最新值，导致控制台没有输出上面的句子。
 *
 * 方法二
 * 因为当一个线程进入 synchronizer 代码块后，线程获取到锁，会清空本地内存，
 * 然后从主内存中拷贝共享变量的最新值到本地内存作为副本，执行代码，又将修改后的副本值刷新到主内存中，最后线程释放锁。
 *
 * @author star
 */
public class VolatileExample {

    /**
     * main 方法作为一个主线程
     */
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        // 开启线程
        myThread.start();

        // 主线程执行
        for (; ; ) {
            if (myThread.isFlag()) {
                System.out.println("主线程访问到 flag 变量");
                break;
            }
        }
    }

}

/**
 * 子线程类
 */
class MyThread extends Thread {

    private volatile boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 修改变量值
        flag = true;
        System.out.println("flag = " + flag);
    }

    public boolean isFlag() {
        return flag;
    }

}
